{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码， 原文地址 http://vra.github.io/2017/12/02/argparse-usage/\n",
    "\n",
    "[argparse](https://docs.python.org/3/library/argparse.html) 是 python 自带的命令行参数解析包，可以用来方便地读取命令行参数，当你的代码需要频繁地修改参数的时候，使用这个工具可以将参数和代码分离开来，让你的代码更简洁，适用范围更广。  \n",
    "argparse 使用比较简单，常用的功能可能较快地实现出来，下面我分几个步骤，**以 Python3 为例**，逐渐递增地讲述 argparse 的用法。\n",
    "\n",
    "### [](#1-基本框架 \"1. 基本框架\")1. 基本框架\n",
    "\n",
    "下面是使用 argparse 从命令行获取用户名，然后打印’Hello ‘+ 用户名，假设 python 文件名为`print_name.py`:\n",
    "\n",
    "```py\n",
    "import argparse\n",
    "\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(description=\"Demo of argparse\")\n",
    "    parser.add_argument('--name', default='Great')\n",
    "    \n",
    "    return parser\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    parser = get_parser()\n",
    "    args = parser.parse_args()\n",
    "    name = args.name\n",
    "    print('Hello {}'.format(name))\n",
    "```\n",
    "\n",
    "在命令行执行如下命令：\n",
    "\n",
    "```\n",
    "$ python print_name.py --name Wang\n",
    "Hello Wang\n",
    "```\n",
    "\n",
    "上面的代码段中，我们显示引入了`argparse`包，然后通过`argparse.ArgumentParser`函数生成 argparse 对象，其中这个函数的`description`函数表示在命令行显示帮助信息的时候，这个程序的描述信息。之后我们通过对象的`add_argument`函数来增加参数。这里我们只增加了一个`--name`的参数，然后后面的`default`参数表示如果没提供参数，我们默认采用的值。即如果像下面这样执行命令：\n",
    "\n",
    "```py\n",
    "$ python print_name.py\n",
    "```\n",
    "\n",
    "则输出是:\n",
    "\n",
    "```\n",
    "$ Hello Great\n",
    "```\n",
    "\n",
    "最后我们通过 argpaser 对象的`parser_args`函数来获取所有参数`args`，然后通过`args.name`的方式得到我们设置的`--name`参数的值，可以看到这里 argparse 默认的参数名就是`--name`形式里面`--`后面的字符串。  \n",
    "整个流程就是这样，下面我们详细讲解`add_argument`函数的一些最常用的参数，使得你看完这个教程之后，能完成科研和工作中的大部分命令解析任务。\n",
    "\n",
    "### [](#2-default：没有设置值情况下的默认参数 \"2. default：没有设置值情况下的默认参数\")2. `default`：没有设置值情况下的默认参数\n",
    "\n",
    "如同上例中展示的，default 表示命令行没有设置该参数的时候，程序中用什么值来代替。\n",
    "\n",
    "### [](#3-required-表示这个参数是否一定需要设置 \"3. required: 表示这个参数是否一定需要设置\")3. `required`: 表示这个参数是否一定需要设置\n",
    "\n",
    "如果设置了`required=True`, 则在实际运行的时候不设置该参数将报错：\n",
    "\n",
    "```\n",
    "...\n",
    "parser.add_argument('-name', required=True)\n",
    "...\n",
    "```\n",
    "\n",
    "则运行下面的命令会报错：\n",
    "\n",
    "```\n",
    "$ python print_name.py\n",
    "usage: print_name.py [-h] --name NAME\n",
    "print_name.py: error: argument --name is required\n",
    "```\n",
    "\n",
    "### [](#4-type：参数类型 \"4. type：参数类型\")4. `type`：参数类型\n",
    "\n",
    "默认的参数类型是 str 类型，如果你的程序需要一个整数或者布尔型参数，你需要设置`type=int`或`type=bool`，下面是一个打印平方的例子：\n",
    "\n",
    "```py\n",
    "import argparse\n",
    "\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        description='Calculate square of a given number')\n",
    "    parser.add_argument('-number', type=int)\n",
    "\n",
    "    return parser\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    parser = get_parser()\n",
    "    args = parser.parse_args()\n",
    "    res = args.number ** 2\n",
    "    print('square of {} is {}'.format(args.number, res))\n",
    "```\n",
    "\n",
    "执行：\n",
    "\n",
    "```\n",
    "$ python square.py -number 5\n",
    "square of 5 is 25\n",
    "```\n",
    "\n",
    "### [](#5-choices：参数值只能从几个选项里面选择 \"5. choices：参数值只能从几个选项里面选择\")5. `choices`：参数值只能从几个选项里面选择\n",
    "\n",
    "如下面的代码：\n",
    "\n",
    "```py\n",
    "import argparse\n",
    "\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        description='choices demo')\n",
    "    parser.add_argument('-arch', required=True, choices=['alexnet', 'vgg'])\n",
    "\n",
    "    return parser\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    parser = get_parser()\n",
    "    args = parser.parse_args()\n",
    "    print('the arch of CNN is '.format(args.arch))\n",
    "```\n",
    "\n",
    "如果像下面这样执行会报错：\n",
    "\n",
    "```\n",
    "$ python choices.py -arch resnet\n",
    "usage: choices.py [-h] -arch {alexnet,vgg}\n",
    "choices.py: error: argument -arch: invalid choice: 'resnet' (choose from 'alexnet', 'vgg')\n",
    "```\n",
    "\n",
    "因为我们所给的`-arch`参数`resnet`不在备选的`choices`之中，所以会报错\n",
    "\n",
    "### [](#6-help：指定参数的说明信息 \"6. help：指定参数的说明信息\")6. `help`：指定参数的说明信息\n",
    "\n",
    "在现实帮助信息的时候，help 参数的值可以给使用工具的人提供该参数是用来设置什么的说明，对于大型的项目，help 参数和很有必要的，不然使用者不太明白每个参数的含义，增大了使用难度。  \n",
    "下面是个例子：\n",
    "\n",
    "```py\n",
    "import argparse\n",
    "\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        description='help demo')\n",
    "    parser.add_argument('-arch', required=True, choices=['alexnet', 'vgg'],\n",
    "        help='the architecture of CNN, at this time we only support alexnet and vgg.')\n",
    "\n",
    "    return parser\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    parser = get_parser()\n",
    "    args = parser.parse_args()\n",
    "    print('the arch of CNN is '.format(args.arch))\n",
    "```\n",
    "\n",
    "在命令行加`-h`或`--help`参数运行该命令，获取帮助信息的时候，结果如下：\n",
    "\n",
    "```sh\n",
    "$ python help.py -h\n",
    "usage: help.py [-h] -arch {alexnet,vgg}\n",
    "\n",
    "choices demo\n",
    "\n",
    "optional arguments:\n",
    "  -h, --help           show this help message and exit\n",
    "  -arch {alexnet,vgg}  the architecture of CNN, at this time we only support\n",
    "                       alexnet and vgg.\n",
    "```\n",
    "\n",
    "### [](#7-dest：设置参数在代码中的变量名 \"7. dest：设置参数在代码中的变量名\")7. `dest`：设置参数在代码中的变量名\n",
    "\n",
    "argparse 默认的变量名是`--`或`-`后面的字符串，但是你也可以通过`dest=xxx`来设置参数的变量名，然后在代码中用`args.xxx`来获取参数的值。\n",
    "\n",
    "### [](#8-nargs：-设置参数在使用可以提供的个数 \"8. nargs： 设置参数在使用可以提供的个数\")8. `nargs`： 设置参数在使用可以提供的个数\n",
    "\n",
    "使用方式如下：\n",
    "\n",
    "```\n",
    "parser.add_argument('-name', nargs=x)\n",
    "```\n",
    "\n",
    "其中`x`的候选值和含义如下：\n",
    "\n",
    "```\n",
    "值  含义\n",
    "N   参数的绝对个数（例如：3）\n",
    "'?'   0或1个参数\n",
    "'*'   0或所有参数\n",
    "'+'   所有，并且至少一个参数\n",
    "```\n",
    "\n",
    "如下例子：\n",
    "\n",
    "```py\n",
    "import argparse\n",
    "\n",
    "def get_parser():\n",
    "    parser = argparse.ArgumentParser(\n",
    "        description='nargs demo')\n",
    "    parser.add_argument('-name', required=True, nargs='+')\n",
    "\n",
    "    return parser\n",
    "\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    parser = get_parser()\n",
    "    args = parser.parse_args()\n",
    "    names = ', '.join(args.name)\n",
    "    print('Hello to {}'.format(names))\n",
    "```\n",
    "\n",
    "执行命令和结果如下：\n",
    "\n",
    "```\n",
    "$ python nargs.py -name A B C\n",
    "Hello to A, B, C\n",
    "```\n",
    "\n",
    "参考链接：\n",
    "\n",
    "1.  [http://blog.xiayf.cn/2013/03/30/argparse/](http://blog.xiayf.cn/2013/03/30/argparse/)\n",
    "2.  [https://docs.python.org/3/library/argparse.html](https://docs.python.org/3/library/argparse.html)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
